package com.jinmdz.fmis.api.admin.service;

import com.jinmdz.fmis.api.admin.model.timesegment.FurnaceTypeCodeData;
import com.jinmdz.fmis.api.admin.model.timesegment.TimeSegmentSaveData;
import com.jinmdz.fmis.api.api.model.common.IdVersionData;
import com.jinmdz.fmis.api.base.BaseService;
import com.jinmdz.fmis.api.model.config.dictionary.OperationLogCode;
import com.jinmdz.fmis.api.model.system.UserItem;
import com.jinmdz.fmis.api.wrapper.DictionaryWrapper;
import com.jinmdz.fmis.api.wrapper.OperationWrapper;
import com.jinmdz.fmis.common.ext.StringBuilderExt;
import com.jinmdz.fmis.common.util.DataUtil;
import com.jinmdz.fmis.core.base.BaseResult;
import com.jinmdz.fmis.core.constant.EDictCode;
import com.jinmdz.fmis.core.exception.ActionException;
import com.jinmdz.fmis.core.util.JacksonUtil;
import com.jinmdz.fmis.dao.admin.dao.TimeSegmentDao;
import com.jinmdz.fmis.dao.admin.model.timesegment.TimeSegmentEditItem;
import com.jinmdz.fmis.dao.admin.model.timesegment.TimeSegmentListItem;
import com.jinmdz.fmis.dao.model.dictionary.DataDictionaryItem;
import com.jinmdz.fmis.mapper.entity.CremationTimeSegmentEntity;
import com.jinmdz.fmis.mapper.mapper.CremationTimeSegmentMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;

/**
 * 火化预约时间段Service
 *
 * @author LiCongLu
 * @date 2020-03-14 14:35
 */
@Service("timeSegmentService")
public class TimeSegmentService extends BaseService {

    @Resource
    private TimeSegmentDao timeSegmentDao;

    @Resource
    private DictionaryWrapper dictionaryWrapper;

    @Resource
    private CremationTimeSegmentMapper cremationTimeSegmentMapper;

    @Resource
    private OperationWrapper operationWrapper;

    @Resource
    private OperationLogCode operationLogCode;

    /**
     * 按照火化炉类型加载火化预约时间段信息
     *
     * @param data 火化炉类型编码
     * @return
     * @author LiCongLu
     * @date 2020-03-14 14:39
     */
    public BaseResult<ArrayList<TimeSegmentListItem>> loadTimeSegmentListWithCode(FurnaceTypeCodeData data) {
        ArrayList<TimeSegmentListItem> loadItems = timeSegmentDao.listTimeSegmentListByCode(data.getFurnaceTypeCode());
        // 设置字典文本
        dictionaryWrapper.resetDataText(loadItems);
        return successList(loadItems);
    }

    /**
     * 保存火化预约时间段信息
     *
     * @param userItem 当前帐号
     * @param data     请求数据
     * @return
     * @author LiCongLu
     * @date 2020-03-12 14:43
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult saveTimeSegment(UserItem userItem, ArrayList<TimeSegmentSaveData> data) throws ActionException {
        // 判断类型
        if (DataUtil.invalid(data)) {
            throw exception("火化预约时间段不能为空！");
        }

        // 判断火化炉类型
        Integer typeCode = data.get(0).getFurnaceTypeCode();
        DataDictionaryItem dataItem = dictionaryWrapper.getDataDictionaryItem(EDictCode.FURNACE_TYPE, typeCode);
        if (DataUtil.isNull(dataItem)) {
            throw exception("火化炉类型错误");
        }

        // 得到火化炉预约时间段
        ArrayList<String> timeSegments = new ArrayList<>();
        for (TimeSegmentSaveData segmentSaveData : data) {
            if (DataUtil.valid(segmentSaveData.getAppointmentTimeSegment())) {
                timeSegments.add(segmentSaveData.getAppointmentTimeSegment());
            }
        }
        // 去重
        timeSegments = DataUtil.repeatArrayList(timeSegments);

        // 判断重复大小
        if (timeSegments.size() != data.size()) {
            throw exception("存在重复的时间段");
        }

        // 记录新增时间段
        ArrayList<CremationTimeSegmentEntity> segmentEntities = new ArrayList<>();

        // 开始时间集合
        ArrayList<String> startList = new ArrayList<>();
        // 结束时间集合
        ArrayList<String> endList = new ArrayList<>();

        // 遍历追加
        for (String timeSegment : timeSegments) {

            // 判断火化预约时间段编号的重复性
            Integer timeSegmentCodeId = timeSegmentDao.getTimeSegmentIdByTimeSegmentCode(timeSegment, typeCode);
            if (DataUtil.valid(timeSegmentCodeId)) {
                throw exception("存在重复的火化预约时间段");
            }

            // 判断时间段格式
            if (!timeSegment.contains("-")) {
                throw exception("存在错误格式的火化预约时间段");
            }

            // 判断时间节点
            String[] times = timeSegment.split("-");
            if (times.length != 2) {
                throw exception("存在错误格式的火化预约时间段");
            }

            // 判断开始时间
            Integer startTimeId = timeSegmentDao.getTimeSegmentIdByStartTime(times[0], typeCode);
            if (startList.contains(times[0]) || DataUtil.valid(startTimeId)) {
                throw exception("存在开始时间重复的火化预约时间段");
            }

            // 判断结束时间
            Integer endTimeId = timeSegmentDao.getTimeSegmentIdByEndTime(times[1], typeCode);
            if (endList.contains(times[1]) || DataUtil.valid(endTimeId)) {
                throw exception("存在结束时间重复的火化预约时间段");
            }

            // 记录开始时间和结束时间
            startList.add(times[0]);
            endList.add(times[1]);

            // 创建实体
            CremationTimeSegmentEntity entity = getEntity(userItem, CremationTimeSegmentEntity.class);

            // 创建关联
            entity.setFurnaceTypeCode(typeCode)
                    .setAppointmentTimeSegment(timeSegment)
                    .setSort(0);

            // 新增火化预约时间段信息
            cremationTimeSegmentMapper.insertCremationTimeSegment(entity);
            // 判断保存火化预约时间段信息结果
            if (DataUtil.invalid(entity.getId())) {
                throw exception("保存火化预约时间段信息失败");
            }

            // 保存新增数据
            segmentEntities.add(entity);
        }

        // 添加操作日志
        saveTimeSegmentLog(userItem, operationLogCode.getInsert(), dataItem, timeSegments, data, segmentEntities);

        return success("保存成功");
    }

    /**
     * 添加火化预约时间段修改记录
     *
     * @param userItem        当前帐号
     * @param logTypeCode     操作日志值
     * @param dataItem        火化炉类型
     * @param timeSegments    当前时间段
     * @param data            请求数据
     * @param segmentEntities 插入数据
     * @return
     * @author LiCongLu
     * @date 2020-03-12 14:45
     */
    private void saveTimeSegmentLog(UserItem userItem, Integer logTypeCode, DataDictionaryItem dataItem, ArrayList<String> timeSegments, ArrayList<TimeSegmentSaveData> data, ArrayList<CremationTimeSegmentEntity> segmentEntities) throws ActionException {
        // 操作日志字符串
        StringBuilderExt builder = new StringBuilderExt();
        builder.format("保存火化预约时间段信息，火化炉类型[{0}][{1}]，火化预约时间段[{2}]，操作人员[{3}]"
                , String.valueOf(dataItem.getDataCode()), dataItem.getDataText()
                , StringUtils.arrayToDelimitedString(timeSegments.toArray(new String[]{}), ",")
                , userItem.getFullName());

        // 添加日志
        operationWrapper.operationLog(userItem, logTypeCode, builder.toString(), JacksonUtil.obj2Json(data), null, JacksonUtil.obj2Json(segmentEntities));
    }

    /**
     * 中删除指定id的火化预约时间段信息记录
     *
     * @param userItem 当前帐号
     * @param data     主键和版本号
     * @return
     * @author LiCongLu
     * @date 2020-03-10 16:33
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult deleteTimeSegmentWithId(UserItem userItem, ArrayList<IdVersionData> data) throws ActionException {
        // 判断删除主键集合是否存在
        if (DataUtil.invalid(data)) {
            throw exception("不存在要删除的火化预约时间段信息");
        }

        // 验证主键是否重复
        if (data.size() != getRepeatIdSize(data)) {
            throw exception("火化预约时间段主键存在重复");
        }

        // 记录火化预约时间段信息集合
        ArrayList<TimeSegmentEditItem> loadItems = new ArrayList<>();

        // 进行遍历删除信息
        for (IdVersionData idData : data) {
            // 通过主键查询火化预约时间段信息
            TimeSegmentEditItem loadItem = timeSegmentDao.getTimeSegmentEditById(idData.getId());
            if (DataUtil.isNull(loadItem) || DataUtil.isNull(loadItem.getId(), loadItem.getVersion())) {
                throw exception("主键错误，不存在此火化预约时间段信息");
            }

            // 验证火化预约时间段信息版本
            if (!DataUtil.equals(loadItem.getVersion(), idData.getVersion())) {
                throw exception(versionError("火化预约时间段信息"));
            }

            // 删除火化预约时间段信息
            cremationTimeSegmentMapper.deletedForCremationTimeSegment(loadItem.getId(), userItem.getId(), loadItem.getVersion());
            // 记录火化预约时间段信息
            loadItems.add(loadItem);
        }

        // 添加操作日志信息
        deleteTimeSegmentLog(userItem, operationLogCode.getDelete(), data, loadItems);

        return success("删除成功");
    }

    /**
     * 添加修改记录
     *
     * @param userItem    当前帐号
     * @param logTypeCode 操作日志值
     * @param data        请求数据
     * @param loadItems   删除信息实体
     * @return
     * @author LiCongLu
     * @date 2020-03-12 14:48
     */
    private void deleteTimeSegmentLog(UserItem userItem, Integer logTypeCode, ArrayList<IdVersionData> data, ArrayList<TimeSegmentEditItem> loadItems) throws ActionException {
        // 操作日志字符串
        StringBuilderExt builder = new StringBuilderExt();
        builder.format("删除火化预约时间段信息，操作人员[{1}]", userItem.getFullName());
        // 添加日志
        operationWrapper.operationLog(userItem, logTypeCode, builder.toString(), JacksonUtil.obj2Json(data), JacksonUtil.obj2Json(loadItems), null);
    }
}
